﻿using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Text;
using System.IO;
using SdmxMl.GenericMetadata;
using SdmxMl.Common;
using SdmxMl.Structure;
using SdmxMl.Manager;
using DW.RtfWriter;
using System.Diagnostics;

namespace SdmxMl.Report
{
    public class HtmlAttributesReport
    {
        private MetadataStructureDefinitionType _msd;
        private AttributeValueSetType attribValueSet;
        private ReportStructureType reportStructure;
        private SmManager sm;
        private bool includeConceptNote;
        private bool includeConceptId;
        private StringBuilder sbHtml;

        public HtmlAttributesReport(MetadataStructureDefinitionType msd)
        {
            _msd = msd;
            sm = ReferenceManager.GetSmContainerImage();
        }


        public string MakeReport(AttributeValueSetType attribValueSet, ReportStructureType rep, bool includeConceptNote, bool incConceptId)
        {
            sbHtml = new StringBuilder(256);

            this.reportStructure = rep;
            this.attribValueSet = attribValueSet;
            this.includeConceptNote = includeConceptNote;
            this.includeConceptId = incConceptId;
            string conceptNote = string.Empty;

            try
            {
                ReportAttributeList(0, attribValueSet.ReportedAttributeList);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Report Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            return sbHtml.ToString();
        }

        private string ValueWithParagraph(string val)
        {
            if (val == null)
                val = string.Empty;
            if (val.StartsWith("<p"))
                return val;
            return ("<p>" + val + "</p>");
        }

        private void ReportAttributeList(int level, ReportedAttributeTypeList rptList)
        {
            string conceptNote = string.Empty;
            foreach (ReportedAttributeType r in rptList)
            {
                string conceptName = GetConceptName(r, ref conceptNote);

                sbHtml.Append("<strong><span style=\"color:green\">");
                sbHtml.Append(conceptName);
                sbHtml.Append(@"</span></strong>");

                if (conceptNote.Length > 0)
                {
                    sbHtml.Append("<small><br>").Append(conceptNote).Append("</small>");
                }

                if (r.Value.IsEmpty == false)
                {
                    // Here PRA
                    if (_msd == null)
                        sbHtml.Append(ValueWithParagraph(r.Value.ToString()));
                    else
                        sbHtml.Append(ValueWithParagraph(GenerateTextFromAttribute(r)));
                }
                else
                    sbHtml.Append("<br>");

                if (r.ReportedAttributeList.Count > 0)
                    ReportAttributeList(level + 1, r.ReportedAttributeList);
            }
        }

        private string GenerateTextFromAttribute(ReportedAttributeType r)
        {
            string val = string.Empty;

            if (r != null && _msd != null)
            {
                val = r.Value.ToString();
                MetadataAttributeType meta = reportStructure.MetadataAttributeList.GetAttributeReferingConcept(r.ConceptID);
                if (meta != null)
                {
                    // value is code of a codelist ?
                    if (meta.RepresentationInfo.IsFilled)
                    {
                        // TODO case codelist in concept
                        CodeListType clt = sm.GetArtefact(SdmxArtefactType.CodeLists, meta.RepresentationInfo) as CodeListType;
                        if (clt != null)
                        {
                            if (meta.MetaOccurence.IsMultiCodes)
                            {
                                string[] arr = val.Split(';');
                                StringBuilder sb = new StringBuilder();

                                for (int i = 0; i < arr.Length; ++i)
                                {
                                    ISdmxHierarchyListItem item = clt.CodeList.LocateItem(arr[i]);
                                    if (item != null)
                                    {
                                        sb.Append(item.Id).Append(" - ").Append(item.Name.ToString());
                                        if (i < arr.Length - 1)
                                            sb.Append("<br>");
                                    }
                                }
                                val = sb.ToString();
                            }
                            else
                            {
                                ISdmxHierarchyListItem item = clt.CodeList.LocateItem(val);
                                if (item != null)
                                    val = val + " - " + item.Name.ToString();
                            }
                        }
                    }
                    else if (meta.TextFormat.TextType == TextTypeType.URI)
                    {
                        string urn = val;
                        ArtefactRefTyped art = null;
                        if (urn.StartsWith(UrnManager.UrnBase))
                        {
                            UrnParser p = new UrnParser(urn);
                            if (p.IsSupported)
                            {
                                art = new ArtefactRefTyped(p.ArType, p.ArtefactId, p.AgencyId, p.Version);

                                if (p.SubType == "Concept")
                                {
                                    ConceptSchemeType cst = sm.GetArtefact(SdmxArtefactType.Concepts, art, true) as ConceptSchemeType;
                                    if (cst != null)
                                    {
                                        ISdmxHierarchyListItem item = cst.ConceptList.LocateItem(p.SubTypeId);
                                        if (item != null)
                                            val = p.SubTypeId + " - " + item.Name.ToString();
                                    }
                                }
                                else if (p.ArType == SdmxArtefactType.CodeLists)
                                {
                                    CodeListType clt = sm.GetArtefact(SdmxArtefactType.CodeLists, art, true) as CodeListType;
                                    if (clt != null)
                                    {
                                        StringBuilder sb = new StringBuilder();
                                        foreach (CodeType c in clt.CodeList)
                                        {
                                            sb.Append(c.Id).Append(" - ").Append(c.Name.ToString());
                                            sb.Append("<br>");
                                        }
                                        val = sb.ToString();

                                    }
                                }
                            }
                        }

                    }
                }
            }

            return val;
        }


        private string GetConceptName(ReportedAttributeType r, ref string conceptNote)
        {
            conceptNote = string.Empty;
            string name = r.ConceptID;
            if (reportStructure != null)
            {
                MetadataAttributeType meta =
                    reportStructure.MetadataAttributeList.GetAttributeReferingConcept(r.ConceptID);
                if (meta != null)
                {
                    ConceptSchemeType cst = ReferenceManager.LocateConceptScheme(meta.ConceptSchemeInfo);
                    ConceptType c = ReferenceManager.LocateConcept(cst, r.ConceptID);
                    if (c != null)
                    {
                        string conceptName = c.Name.ToString();
                        if (conceptName.Length > 0)
                        {
                            if (includeConceptId)
                                name += " - " + conceptName;
                            else
                                name = conceptName;
                        }
                        if (includeConceptNote)
                        {
                            conceptNote = c.AnnotationList.GetTextOfAnnotationType("CONTEXT");
                            if (string.IsNullOrEmpty(conceptNote))
                                if (c.Description.ToString() != MultiLang.UndefinedText)
                                    conceptNote = c.Description.ToString();
                        }
                    }
                }
            }
            return name;
        }




    }
}
